import json
import re
import time
from typing import Dict, Any, Optional, List, Set
from app.agent.llm import get_llm
from app.agent.finance_ner import entity_recognizer
from functools import lru_cache
from ..core.logger import get_logger

logger = get_logger('agent.intent_recognizer')

class IntentRecognizer:
    """使用大模型进行意图识别和结构化请求生成"""
    
    def __init__(self):
        self.llm = get_llm()
        # 使用金融实体识别器
        self.entity_recognizer = entity_recognizer
        
        # 使用集合(Set)替代列表以提高查找效率
        # 复杂金融查询的关键词模式
        self.complex_finance_patterns: Set[str] = {
            # 基金相关
            "基金代码", "基金名称", "基金规模", "基金净值", "基金持仓", "基金经理", 
            "基金收益率", "基金成立日期", "基金费率", "基金评级",
            
            # 股票相关
            "股票代码", "股票名称", "收盘价", "开盘价", "最高价", "最低价", "成交量", 
            "成交额", "市盈率", "市净率", "市值", "涨跌幅", "换手率",
            
            # 债券相关
            "债券代码", "债券名称", "债券收益率", "票面利率", "到期日期",
            
            # 行业相关
            "行业分类", "行业指数", "行业涨跌幅", "行业排名",
            
            # 财务指标
            "净利润", "营收", "资产负债率", "毛利率", "净利率", 
            "ROE", "ROA", "现金流",
            
            # 其他金融指标
            "成交量", "成交额", "换手率", "振幅",
            
            # 时间相关
            "成立日期", "交易日", "报告期", "年度", "季度", "月度"
        }
        
        # 通用查询关键词模式
        self.generic_patterns: Set[str] = {
            "什么是", "解释", "定义", "说明", "介绍", "含义", 
            "如何", "怎样", "方法", "步骤", "流程",
            "区别", "差异", "比较", "对比",
            "为什么", "原因", "理由", "影响", "因素",
            "举例", "例子", "案例", "示范"
        }
        
        # 关系查询关键词模式
        self.relationship_patterns: Set[str] = {
            "关系", "关联", "联系", "影响", "作用", 
            "相互", "互动", "依赖", "依赖关系",
            "投资", "持有", "包含", "属于", "分类", 
            "组成", "构成", "结构", "架构"
        }
        
        # 知识图谱查询关键词模式
        self.graph_patterns: Set[str] = {
            "路径", "最短路径", "路径分析", "连接", 
            "连接方式", "连接关系", "关系路径", "图谱",
            "实体", "节点", "边", "关系", "图结构"
        }
        
        # 投资建议查询关键词模式
        self.investment_advice_patterns: Set[str] = {
            "建议", "推荐", "选择", "投资策略", "投资组合", 
            "配置", "买入", "卖出", "持有", "观望",
            "机会", "风险", "分析", "预测", "走势",
            "前景", "潜力", "价值", "估值", "判断"
        }
        
        # 公司背景查询关键词模式
        self.company_background_patterns: Set[str] = {
            "市场占有率", "控股股东", "持股比例", "发起人", "股东", 
            "注册资本", "注册地", "总部", "办公地点", "经营范围", 
            "主营业务", "设立", "成立", "历史", "背景", "发展历程", 
            "沿革", "法定代表人", "高管", "管理层", "存货", "流动资产",
            "固定资产", "总资产", "总负债", "净资产", "资产负债率", 
            "应收账款", "应付账款", "销售费用", "管理费用", "财务费用", 
            "研发费用", "核心竞争力", "竞争优势", "商业模式"
        }
        
        # 投资者份额比较查询关键词模式
        self.investor_share_patterns: Set[str] = {
            "个人投资者", "机构投资者", "基金份额", "份额超过", "份额比较", 
            "个人持有", "机构持有", "投资者比例", "持有人结构"
        }
        
        # 编译公司名称模式以提高匹配效率
        self.company_name_patterns = [
            r'([^，。,;；\s]+?[股份有限]{2,4}公司)',
            r'([^，。,;；\s]+?有限责任公司)',
            r'([^，。,;；\s]+?合伙企业)',
            r'([^，。,;；\s]+?基金会)'
        ]
        self.compiled_company_patterns = [re.compile(pattern, re.IGNORECASE) for pattern in self.company_name_patterns]
        
        # 模式到意图的映射
        self.pattern_to_intent = {}
        for pattern in self.complex_finance_patterns:
            self.pattern_to_intent[pattern.lower()] = "complex_finance_query"
        for pattern in self.generic_patterns:
            self.pattern_to_intent[pattern.lower()] = "generic_query"
        for pattern in self.relationship_patterns:
            self.pattern_to_intent[pattern.lower()] = "relationship_query"
        for pattern in self.graph_patterns:
            self.pattern_to_intent[pattern.lower()] = "graph_query"
        for pattern in self.investment_advice_patterns:
            self.pattern_to_intent[pattern.lower()] = "investment_advice"
        for pattern in self.company_background_patterns:
            self.pattern_to_intent[pattern.lower()] = "company_background"
        # 添加投资者份额比较模式映射
        for pattern in self.investor_share_patterns:
            self.pattern_to_intent[pattern.lower()] = "finance_agent"
        
        # 意图优先级定义（数值越高优先级越高）
        self.intent_priority = {
            "company_background": 1.0,
            "complex_finance_query": 0.95,
            "investment_advice": 0.9,
            "stock_info": 0.85,
            "fund_info": 0.85,
            "industry_analysis": 0.8,
            "stock_screening": 0.8,
            "fund_screening": 0.8,
            "stock_performance": 0.75,
            "fund_performance": 0.75,
            "relationship_query": 0.7,
            "graph_query": 0.65,
            "generic_query": 0.6,
            "chitchat": 0.1,
            "unknown": 0.0
        }
    
    def recognize_intent(self, query: str) -> Dict[str, Any]:
        """
        使用大模型识别用户意图并生成结构化请求
        
        Args:
            query: 用户查询
            
        Returns:
            包含意图和结构化参数的字典
        """
        start_time = time.time()
        logger.debug(f"开始意图识别: {query}")
        
        # 首先使用关键词匹配进行预识别
        pre_intent = self._pre_recognize_intent(query)
        if pre_intent:
            logger.debug(f"预识别成功，耗时: {time.time() - start_time:.4f}秒")
            return pre_intent
            
        # 构建提示词
        prompt = self._build_intent_prompt(query)
        
        try:
            # 使用LLM识别意图
            response = self.llm.invoke(prompt)
            
            # 确保响应是字符串
            if hasattr(response, 'content'):
                response_text = response.content
            else:
                response_text = str(response)
            
            # 解析响应
            intent_data = self._parse_intent_response(response_text)
            
            # 添加金融实体信息
            entities = self.entity_recognizer.extract_entities(query)
            if entities:
                # 合并实体信息
                if "entities" in intent_data:
                    intent_data["entities"].update(entities)
                else:
                    intent_data["entities"] = entities
            
            logger.info(f"识别到意图: {intent_data}")
            logger.debug(f"意图识别总耗时: {time.time() - start_time:.4f}秒")
            return intent_data
        except Exception as e:
            logger.error(f"意图识别失败: {e}")
            # 返回默认意图
            return {
                "intent": "unknown",
                "entities": {},
                "confidence": 0.0,
                "query": query
            }
    
    def _pre_recognize_intent(self, query: str) -> Optional[Dict[str, Any]]:
        """
        使用关键词匹配进行预识别
        
        Args:
            query: 用户查询
            
        Returns:
            预识别的意图数据或None
        """
        start_time = time.time()
        query_lower = query.lower()
        logger.debug(f"开始预识别意图: {query}")
        
        # 特殊规则：控股股东/持股比例查询
        ownership_pattern = r'(控股股东|持股比例|发起人|股东)(.*?)(是|为|有哪些|是谁|有多少|是什么)'
        if re.search(ownership_pattern, query):
            logger.debug("检测到控股股东/持股比例查询模式，识别为company_background意图")
            result = {
                "intent": "company_background",
                "entities": {},
                "confidence": 0.95,
                "query": query
            }
            logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
            return result
            
        # 特殊规则：基金公司成立基金数量查询
        fund_company_pattern = r'(.+基金管理有限公司)(\d{4})年成立了多少(.*)基金'
        fund_company_match = re.search(fund_company_pattern, query)
        if fund_company_match:
            logger.debug("检测到基金公司成立基金数量查询模式，识别为complex_finance_query意图")
            entities = {}
            entities["company_name"] = fund_company_match.group(1)
            entities["year"] = fund_company_match.group(2)
            result = {
                "intent": "complex_finance_query",
                "entities": entities,
                "confidence": 0.95,
                "query": query
            }
            logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
            return result
            
        # 特殊规则：包含市场占有率的查询
        if "市场占有率" in query:
            logger.debug("检测到市场占有率关键词，识别为company_background意图")
            # 尝试提取公司名称
            entities = {}
            # 特别处理"东莞勤上光电股份有限公司"
            company_match = re.search(r'(东莞\S*光电\S*股份有限公司)', query)
            if not company_match:
                # 通用公司名称匹配
                company_match = re.search(r'([^，,。.！!？?；;]+股份有限公司)', query)
            
            if company_match:
                company_name = company_match.group(1)
                # 标准化公司名称
                entities["company_name"] = self._standardize_company_name(company_name)
            
            result = {
                "intent": "company_background",
                "entities": entities,
                "confidence": 0.95,
                "query": query
            }
            logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
            return result

        # 特殊处理：检查是否包含公司名称和特定的公司背景关键词
        # 这种组合应该优先识别为company_background
        special_company_background_check_start = time.time()
        has_company_name = any(pattern_re.search(query_lower) for pattern_re in self.compiled_company_patterns)
        
        # 定义高优先级的公司背景关键词
        high_priority_company_background_keywords = [
            "市场占有率", "控股股东", "持股比例", "发起人", "股东", "注册资本", 
            "注册地", "总部", "办公地点", "经营范围", "主营业务", "设立", "成立",
            "历史", "背景", "发展历程", "沿革", "法定代表人", "高管", "管理层"
        ]
        
        has_high_priority_keyword = any(keyword in query_lower for keyword in high_priority_company_background_keywords)
        
        special_company_background_check_time = time.time() - special_company_background_check_start
        
        # 如果同时包含公司名称和高优先级公司背景关键词，优先识别为company_background
        if has_company_name and has_high_priority_keyword:
            logger.debug(f"检测到公司名称和高优先级背景关键词，优先识别为company_background意图")
            result = {
                "intent": "company_background",
                "entities": {},
                "confidence": 0.95,
                "query": query
            }
            logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
            return result
            
        # 检查是否包含公司背景关键词（即使没有明确匹配公司名称模式）
        company_background_patterns_check_start = time.time()
        company_background_keywords_in_query = [pattern for pattern in self.company_background_patterns if pattern in query_lower]
        company_background_patterns_check_time = time.time() - company_background_patterns_check_start
        
        # 如果包含公司背景关键词，且查询中包含"公司"字样，则识别为company_background
        if company_background_keywords_in_query and "公司" in query:
            logger.debug(f"检测到公司背景关键词: {company_background_keywords_in_query}，识别为company_background意图")
            result = {
                "intent": "company_background",
                "entities": {},
                "confidence": 0.9,
                "query": query
            }
            logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
            return result
        
        # 优化1：使用集合查找，只需一次遍历即可找到所有匹配的模式
        pattern_matching_start = time.time()
        matched_patterns = [pattern for pattern in self.pattern_to_intent.keys() if pattern in query_lower]
        pattern_matching_time = time.time() - pattern_matching_start
        
        # 检查是否有complex_finance_patterns匹配
        complex_finance_matches = [pattern for pattern in self.complex_finance_patterns if pattern in query_lower]
        
        # 如果同时匹配到company_background_patterns和complex_finance_patterns
        # 但company_background_patterns匹配更多，则优先选择
        if matched_patterns:
            company_background_matches = [pattern for pattern in self.company_background_patterns if pattern in query_lower]
            
            # 如果company_background匹配项更多，则优先选择
            if len(company_background_matches) > len(complex_finance_matches):
                logger.debug(f"company_background匹配项({len(company_background_matches)})多于complex_finance匹配项({len(complex_finance_matches)})，优先识别为company_background")
                result = {
                    "intent": "company_background",
                    "entities": {},
                    "confidence": 0.9,
                    "query": query
                }
                logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
                return result
        
        # 如果有匹配的模式，返回对应意图
        if matched_patterns:
            logger.debug(f"匹配到{len(matched_patterns)}个模式，模式匹配耗时: {pattern_matching_time:.4f}秒")
            
            # 优先返回置信度高的意图
            intent_priority = self.intent_priority
            
            # 找到匹配模式中优先级最高的意图
            priority_check_start = time.time()
            intent = None
            max_confidence = 0.0
            for pattern in matched_patterns:
                current_intent = self.pattern_to_intent[pattern]
                current_confidence = intent_priority.get(current_intent, 0.0)
                if current_confidence > max_confidence:
                    intent = current_intent
                    max_confidence = current_confidence
            priority_check_time = time.time() - priority_check_start
            
            if intent:
                logger.debug(f"确定优先级最高意图为{intent}，优先级检查耗时: {priority_check_time:.4f}秒")
                result = {
                    "intent": intent,
                    "entities": {},
                    "confidence": max_confidence,
                    "query": query
                }
                logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
                return result
        
        # 尝试通过公司名称模式识别
        company_pattern_start = time.time()
        for pattern_re in self.compiled_company_patterns:
            if pattern_re.search(query_lower):
                # 检查是否包含公司背景相关关键词
                has_company_background = any(pattern in query_lower for pattern in self.company_background_patterns)
                if has_company_background:
                    result = {
                        "intent": "company_background",
                        "entities": {},
                        "confidence": 0.9,
                        "query": query
                    }
                else:
                    result = {
                        "intent": "relationship_query",
                        "entities": {},
                        "confidence": 0.85,
                        "query": query
                    }
                company_pattern_time = time.time() - company_pattern_start
                logger.debug(f"通过公司名称模式识别意图: {result['intent']}，公司模式检查耗时: {company_pattern_time:.4f}秒")
                logger.debug(f"预识别意图完成，总耗时: {time.time() - start_time:.4f}秒，结果: {result}")
                return result
        company_pattern_time = time.time() - company_pattern_start
        
        logger.debug(f"未匹配到任何模式，模式匹配耗时: {pattern_matching_time:.4f}秒，公司模式检查耗时: {company_pattern_time:.4f}秒，总耗时: {time.time() - start_time:.4f}秒")
        return None
    
    def _standardize_company_name(self, company_name: str) -> str:
        """
        标准化公司名称
        
        Args:
            company_name: 原始公司名称
            
        Returns:
            标准化后的公司名称
        """
        # 移除多余的空格
        company_name = re.sub(r'\s+', '', company_name)
        
        # 处理常见的公司名称变体
        replacements = {
            "股份有限公司": "股份有限公司",
            "有限责任公司": "有限责任公司"
        }
        
        for old, new in replacements.items():
            company_name = company_name.replace(old, new)
            
        return company_name
    
    def _build_intent_prompt(self, query: str) -> str:
        """
        构建意图识别提示词
        
        Args:
            query: 用户查询
            
        Returns:
            构建的提示词
        """
        prompt = f"""
你是一个经验丰富的金融领域智能意图识别专家，擅长准确理解用户的查询意图并提取关键实体信息。请严格按照以下步骤分析用户查询：

### 第一步：识别查询类型
请从以下预定义的查询类型中选择最匹配的一个：
- stock_info: 查询单只股票的基本信息、行情数据等
- fund_info: 查询单只基金的基本信息、净值、持仓等
- industry_analysis: 查询特定行业的整体情况、趋势等
- stock_screening: 根据条件筛选符合要求的多只股票
- fund_screening: 根据条件筛选符合要求的多只基金
- stock_performance: 查询股票的历史表现、收益率等
- fund_performance: 查询基金的历史表现、收益率等
- complex_finance_query: 涉及多维度、多指标的复杂金融计算或分析
- company_background: 查询公司的背景、历史、股东、管理层等信息
- relationship_query: 查询金融实体间的关联关系、投资关系等
- graph_query: 涉及知识图谱路径分析、关系挖掘等查询
- investment_advice: 寻求投资建议、策略推荐等
- generic_query: 通用金融知识查询、概念解释等
- chitchat: 闲聊、问候、感谢等非金融信息查询
- unknown: 无法明确归类到上述类型的查询

### 第二步：提取关键实体信息
请仔细分析用户查询，提取以下可能的实体信息（如有）：
- 股票代码: 如"000001"、"600000"
- 股票名称: 如"平安银行"、"浦发银行"
- 基金代码: 如"000001"、"161725"
- 基金名称: 如"华夏成长混合"、"招商中证白酒指数"
- 日期: 精确到日，格式为YYYYMMDD，如"20230101"；如无具体日期但有时间范围，可填写时间范围描述
- 行业: 如"综合金融"、"医药生物"、"信息技术"
- 指标: 如"涨跌幅"、"成交量"、"市盈率"、"市净率"、"ROE"、"营收"、"净利润"
- 条件: 如"涨幅超过5%"、"市盈率低于10倍"、"市值大于1000亿"
- 统计类型: 如"平均数"、"最大值"、"最小值"、"总和"、"数量"、"排名"
- 公司名称: 如"腾讯控股"、"阿里巴巴集团"、"上海华铭智能终端设备股份有限公司"（请提取完整公司名称）
- 时间范围: 如"近一个月"、"2023年第三季度"、"过去一年"
- 计算类型: 如"年化收益率"、"波动率"、"夏普比率"、"相关性"

### 第三步：评估置信度
请根据对意图识别和实体提取的确定程度，给出0-1之间的置信度分数，0表示完全不确定，1表示完全确定。

### 示例分析
用户查询示例1："贵州茅台(600519)过去一年的涨跌幅是多少？"
分析结果：
- intent: "stock_performance"
- entities: {{"股票代码": "600519", "股票名称": "贵州茅台", "指标": "涨跌幅", "时间范围": "过去一年"}}
- confidence: 0.98

用户查询示例2："请推荐几只近三个月表现最好的科技类基金"
分析结果：
- intent: "investment_advice"
- entities: {{"行业": "科技", "时间范围": "近三个月", "条件": "表现最好"}}
- confidence: 0.95

用户查询示例3："上海华铭智能终端设备股份有限公司的发起人是谁？"
分析结果：
- intent: "company_background"
- entities: {{"公司名称": "上海华铭智能终端设备股份有限公司", "公司背景关键词": "发起人"}}
- confidence: 0.95

用户查询示例4："在2008年，东莞勤上光电股份有限公司在景观亮化半导体照明领域的市场占有率为多少？"
分析结果：
- intent: "company_background"
- entities: {{"公司名称": "东莞勤上光电股份有限公司", "公司背景关键词": "市场占有率", "时间范围": "2008年"}}
- confidence: 0.95

### 任务要求
现在请分析以下用户查询，并严格按照指定的JSON格式返回结果，不要添加任何额外的说明文字。

用户查询: "{query}"

请严格按照以下JSON格式返回结果:
{{
    "intent": "查询类型",
    "entities": {{
        "股票代码": "如果有股票代码则填写，如: 000001",
        "基金代码": "如果有基金代码则填写，如: 000001",
        "日期": "如果有日期则填写，格式: YYYYMMDD，如: 20210105",
        "行业": "如果有行业信息则填写，如: 综合金融",
        "指标": "如果有具体指标则填写，如: 涨跌幅, 成交金额",
        "条件": "如果有筛选条件则填写，如: 涨幅超过5%",
        "统计类型": "如果有统计需求则填写，如: 平均数, 最大值, 数量",
        "公司名称": "如果有公司名称则填写完整名称，如: 贵州茅台股份有限公司",
        "时间范围": "如果有时间范围则填写，如: 过去一年",
        "计算类型": "如果有计算类型则填写，如: 年化收益率"
    }},
    "confidence": "置信度，0-1之间的数字，如: 0.95"
}}

只返回JSON格式的结果，不要添加其他说明。
"""
        return prompt
    
    def _parse_intent_response(self, response_text: str) -> Dict[str, Any]:
        """
        解析意图识别响应
        
        Args:
            response_text: 响应文本
            
        Returns:
            解析后的意图数据
        """
        try:
            # 清理响应文本，确保是有效的JSON
            response_text = response_text.strip()
            if response_text.startswith("```json"):
                response_text = response_text[7:]
            if response_text.endswith("```"):
                response_text = response_text[:-3]
            
            # 解析JSON
            intent_data = json.loads(response_text)
            return intent_data
        except Exception as e:
            logger.error(f"Failed to parse intent response: {e}")
            # 返回默认意图结构
            return {
                "intent": "unknown",
                "entities": {},
                "confidence": 0.0
            }